# -*- encoding:utf-8 -*-
from rest_framework import serializers
from .models import User
import re
from .utils import get_user_by_account
from django.contrib.auth.hashers import make_password
from rest_framework_jwt.settings import api_settings # 手动生成token
from django_redis import get_redis_connection

class UserModelSerializer(serializers.ModelSerializer):
    """
        用户信息序列化器
        前端 -> 后端 数据  write_only
        后端 -> 前端 数据  read_only
    """
    sms_code = serializers.CharField(label='短信验证码',min_length=4,max_length=6, required=True,write_only=True )
    token = serializers.CharField(max_length=1024,read_only=True,help_text="token认证字符串")   #read_only因为注册不需要生成token，而注册好后端返回前端token，所以是read_only
    class Meta:
        model = User
        #提供哪些字段数据，如果在数据库中没有的字段，需要再上面额外声明
        fields = ["id","username","mobile","password","sms_code","token"]
        # 额外声明字段属性  sms_code和mobile 都是前端发给后端的需要反序列化，所以sms_code上面定义了write_only
        # 但是后端mobile是数据库中早定义好的，所以需要extra_kwargs额外定义数据库中的字段的属性write_only
        extra_kwargs = {
            "mobile": {
                "write_only": True
            },
            "password": {
                "write_only": True
            },
            "id":{
                "read_only": True
            },
            "username": {
                "read_only": True
            },
        }
    # ModelSerializer 会将前端传来的数据全部往数据库里塞，有一些新定义的字段不是数据库中的，所以调用原来方法会报错
    # 所以，保存数据之前，将不必要的字段清掉，

    def validate(self, attrs):
        """
            验证用户信息
        :param attrs:
        :return:
        """
        mobile = attrs.get("mobile")
        sms_code = attrs.get("sms_code")
        password = attrs.get("password")
        #验证手机号码格式
        if not re.match(r"^1[3-9]\d{9}$",mobile):
             raise serializers.ValidationError("对不起，手机号格式有误")
        #验证手机是否已经被注册过
        if get_user_by_account(mobile) is not None:
            raise serializers.ValidationError("对不起，手机号已经被注册过")

        # 验证短信验证码是否正确
        redis_conn = get_redis_connection("sms_code")
        real_sms_code = redis_conn.get("sms_%s"%(mobile))   # b'013245' 类型
        # 注意： 从redis数据库中读取的数据，都是字符串，都是bytes类型，需要decode转换成字符串
        # 防止爬虫暴力破解一遍遍测试，都将这个值删掉，只要验证，不管是否正确都删除这个值
        redis_conn.delete("sms_%s" % (mobile))
        if real_sms_code.decode() != sms_code:
            raise serializers.ValidationError("对不起，短信验证码错误，本次验证码失效，请重新获取")

        return attrs


    def create(self, validated_data):
        """
            保存用户信息
            validated_data 就是上面函数中返回的 attrs
        """
        # 删除 不需要 保存 到数据库 的字段
        validated_data.pop("sms_code")

        # 对密码加密
        raw_password = validated_data.get("password")
        hash_password = make_password(raw_password)

        # 用户名设置一个默认值
        username = validated_data.get("mobile")

        # 调用 父类 序列化器 提供create方法
        user = User.objects.create(
            mobile=username,
            username=username,
            password=hash_password
        )

        # 使用restframework_jwt模块提供手动生成token方法生成登录状态
        jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
        jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

        payload = jwt_payload_handler(user)
        # 将token添加到user中
        user.token = jwt_encode_handler(payload)
        return user








from order.models import Order
class UserOrderModelSerializer(serializers.ModelSerializer):
    class Meta:
        model=Order
        # course_list 不用一层层定义序列化器嵌套了，直接在模型里面新增方法直接求出来返回
        fields = ["id","order_number","order_status","created_time","course_list"]







































